/**
 * 
 * @Project le cOeur - Data Virtualization
 * @Date 08.12.2012
 * @Author Aebi Pascal, Kocher Marc
 * @School BFH-TI Biel, Bachelor Thesis
 *
 */

package main.api.http;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * This class represents a component defined by the HTTP protocol (RFC-2616).
 */
public class RequestLine extends StartLine {

	private String requestLine;
	private Method method;
	private URI requestedURI;
	private Version version;
	
	/**
	 * Creates a HTTP request line from a given string.
	 * The created HTTP request line needs to be parsed before the object can be used.
	 * 
	 * @param requestLine The request line string containing the HTTP method, the requested URI and the HTTP method.
	 */
	public RequestLine(String requestLine) {
		this.requestLine = requestLine;
	}

	/**
	 * Creates a HTTP request line.
	 * 
	 * @param method The HTTP method.
	 * @param requestedURI The requested URI.
	 * @param version The HTTP version.
	 */
	public RequestLine(Method method, URI requestedURI, Version version) {
		this.method = method;
		this.requestedURI = requestedURI;
		this.version = version;
	}
	
	@Override
	public void parse() {
		Pattern pattern = Pattern.compile("(OPTIONS|GET|HEAD|POST|PUT|DELETE|TRACE|CONNECT)\\s((?:(?:(\\w*)(?:://))|(?://))?(?:((?:(?:[\\w\\d-\\._]*@)?(?:[\\w\\d-\\._]*[a-zA-Z]{2,3}))|(?:(?:2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.(?:2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.(?:2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.(?:2[0-4]\\d|25[0-5]|[01]?\\d\\d?))))?(?:(?::)(\\d{2,}))?((?:(?:/)[\\w\\d-_]*)+(?:[\\w\\d-_]*\\.[\\w\\d]{1,5})?)(?:(?:\\?)((?:[\\w\\d-_]*=[\\w\\d-_]*)(?:(?:&)(?:[\\w\\d-_]*=[\\w\\d-_]*))*))?(?:(?:\\#)([\\w\\d-\\._]*))?)\\s(HTTP/\\d.\\d)");
		Matcher matcher = pattern.matcher(this.requestLine);
		matcher.find();
		this.method = Method.valueOf(matcher.group(1));
		try {
			this.requestedURI = new URI(matcher.group(2));
		} catch (URISyntaxException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		this.version = Version.getFromValue(matcher.group(9));
	}
	
	@Override
	public String compose() {
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append(this.method);
		stringBuilder.append(" ");
		stringBuilder.append(this.requestedURI.getPath());
		stringBuilder.append(" ");
		stringBuilder.append(this.version.getValue());
		stringBuilder.append("\r\n");
		return stringBuilder.toString();
	}
	
	@Override
	public String toString() {
		return this.compose();
	}

	/**
	 * Returns the method of the request line header.
	 * 
	 * @return The HTTP method.
	 */
	public Method getMethod() {
		return this.method;
	}

	/**
	 * Returns the requested URI of the request line header.
	 * 
	 * @return The requested URI.
	 */
	public URI getRequestedURI() {
		return this.requestedURI;
	}

	/**
	 * Returns the version of the request line header.
	 * 
	 * @return The HTTP version.
	 */
	public Version getVersion() {
		return this.version;
	}

}
